#ifndef PW_PBL_NUMBERS_HPP
#define PW_PBL_NUMBERS_HPP

#include "Math.hpp"
#include <limits>
#include <concepts>

namespace pw_pbl::inline Numbers
{
	constexpr struct
	{
		template <typename T>
		consteval operator T() const noexcept { return std::numeric_limits<T>::max(); }

		template <size_t BITS>
		consteval operator SBitInt<BITS>() const noexcept { return ~UBitInt<BITS>(0) >> 1; }
		template <size_t BITS>
		consteval operator UBitInt<BITS>() const noexcept { return ~UBitInt<BITS>(0); }
	} EMax{};

	constexpr struct
	{
		template <typename T>
		consteval operator T() const noexcept { return std::numeric_limits<T>::min(); }

		template <size_t BITS>
		consteval operator SBitInt<BITS>() const noexcept { return UBitInt<BITS>(1) << BITS - 1; }
		template <size_t BITS>
		consteval operator UBitInt<BITS>() const noexcept { return 0; }
	} EMin{};

	constexpr struct
	{
		template <std::integral T>
		consteval operator T() const noexcept { return ~T(0); }
	} EAllOne{};

	template <char... C>
	constexpr auto EInt = [] {
		constexpr std::array<char, sizeof...(C)> str = {C...};
		std::uintmax_t value = 0;
		for (auto c : str)
		{
			if (c == '\'')
				continue;
			if (c < '0' || c > '9')
				Throw("format error");
			if (Math::MulOverflow(10, &value) || Math::AddOverflow(c - '0', &value))
				Throw("overflow");
		}
		return value;
	}();
} // namespace pw_pbl::inline Numbers

#endif // PW_PBL_NUMBERS_HPP
